서비스워커 알림(Service Worker Notification)
React
2022.08.29.
Mobile Notification
TimeLog의 알람으로 사용할 notification을 만들며 얻은 것들을 공유합니다.
new Notification()
Constructor로 생성한 알림은 모바일에서 작동하지 않습니다.
Service worker의 showNotification()
Method를 사용하면 모바일에서도 작동하고, 알림에 버튼(actions)을 추가할 수도 있습니다.
이전 글에서 다룬 타이머를 countdown 타이머로 만들고, notification을 더하여 알람 타이머를 만들었습니다.
Service Worker
- Web worker와 마찬가지로 Main thread와 별개로 Background thread에서 script를 실행합니다.
- 보안상의 이유로 HTTPS 프로토콜과 localhost에서만 작동합니다.
- Script 파일(service-worker.js)을 public 폴더에 저장해야 정상 작동합니다.
Service worker의 Life cycle 특성상 업데이트를 반영하려면 새로고침이 필요합니다. (참고 링크 참조)
하지만 저는 처음 접속할 때도 새로고침을 하지 않으면 Service worker가 동작하지 않는 현상이 있습니다.
아직 그 원인을 찾지 못해 임시 해결책으로 사이트 접속 시 한 번 새로고침 되도록 하였습니다.
React
// service-worker.js
self.addEventListener('notificationclick', (event) => {
event.waitUntil(
//서비스워커 종료 방지
clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
clientList[0].focus(); // 해당 페이지 포커스
})
);
});
// React
...
const notificationRequest = () =>
Notification.requestPermission((permission) => {
if (permission === "denied") {
window.alert("Please allow notifications access to continue");
}
});
const notificationOption = {
body: "Body",
icon: "icon.jpg",
actions: [{ title: "Check", action: "check" }],
tag: "notification-tag",
requireInteraction: true,
renotify: true, // 알림 중첩 시 미작동 방지
};
useEffect(() => {
notificationRequest();
// 서비스워커 등록
navigator.serviceWorker.register(
`${process.env.PUBLIC_URL}/service-worker.js`
);
}, []);
useEffect(() => {
if (time === 0) {
// 서비스워커가 활성화 되었다면 알림 실행
navigator.serviceWorker.ready.then((registration) => {
registration.showNotification("Title", notificationOption);
});
}
}, [time]);
...
새로고침 추가
const navigationTiming = performance.getEntriesByType('navigation')[0];
// 새로고침 무한 루프 방지
if (navigationTiming.type === 'navigate') {
window.location.reload();
}